#ifndef PMESH_H_
#define PMESH_H_

#include "PElement.h"
#include <istream>
#include <iostream>
#include <ostream>

using std::istream;
using std::ios;

class PMesh{
private:
	PElement *elements;
	Node *nodes;
	int numOfE,numOfN,hsize,vsize;
	double beta,dt;
public:
	PMesh();
	virtual ~PMesh();
	PMesh(const int &hsize, const int &vsize);
	
	void setNumOfN(const int &numOfN){
		this->numOfN=numOfN;
		this->nodes=new Node[numOfN+1];
	}
	void setNumOfE(const int &numOfE){
		this->numOfE=numOfE;
		this->elements=new PElement[numOfE+1];
	}
	int & NumOfN(){return numOfN;}
	int & NumOfE(){return numOfE;}
	int & Hsize(){return hsize;}
	int & Vsize(){return vsize;}
	
	void setTimeCN(const double &beta, const double &dt){
		this->beta=beta;
		this->dt=dt;
	}
	
	double & Beta(){return beta;}
	double & Dt(){return dt;}
	
	Matrix assembleGlobalCond(const double &rho, const double &cp);
	Matrix assembleGlobalGradien(const double &kx,const double &ky,const double &w);
	Matrix assembleGlobalConv(const double &h,const double &w);
	Matrix assembleStiff(const double &rho,const double &cp, const double &kx, const double &ky, const double &h, const double &w);
	
	Vector assembleGlobalForce(const double &q,const double &h,const double &w,const double &gen, const double &Tf);
	
	Vector assembleForce(const double &q,const double &h,const double &w,const double &gen, const double &Tf,const double &rho, const double &cp, const double &kx, const double &ky);
	
	Vector & nodesT();
	
	void readNodeData(const char *filename);
	
	void readElementData(const char *filename);
	
	void addElement(int i, const PElement &e){
		elements[i]=e;
	}
	PElement & operator()(int i){
		return elements[i];
	}
	void addNode(int i,const Node &n){
		nodes[i]=n;
	}
	Node & operator[](int i){
		return nodes[i];
	}
	
	void assignInitial(Vector &T0){
		for(int i=1;i<=numOfN;i++){
			nodes[i].setT(T0(i));
		}
		int pr=0;
          for(int j=1;j<=numOfE;j++){
        	  for(int k=1;k<=numOfN;k++){
        		pr=elements[j].indexOf(nodes[k]);
        		if(pr>0){
        			elements[j][pr].setT(nodes[k].T());
        		}
        		
        	 }
         }
		
	}
	void assignFluxBC(int i,const int &bc1,const int &bc2){
		elements[i].setFB1(bc1);
		elements[i].setFB2(bc2);
	}
	void assignConvBC(int i,const int &bc1,const int &bc2){
		elements[i].setCB1(bc1);
		elements[i].setCB2(bc2);
	}
	
	void updateT(Vector &T0){
	   double xmin=nodes[1].X();
	   double xmax=nodes[numOfN].X();
	   for(int i=hsize;i<=numOfN;i++){
		if(nodes[i].X()==xmin || nodes[i].X()==xmax){
			nodes[i].setT(nodes[i].T());
		}else{
			nodes[i].setT(T0(i));
		}
		
        }
        int pr=0;
        for(int j=1;j<=numOfE;j++){
        	for(int k=1;k<=numOfN;k++){
        		pr=elements[j].indexOf(nodes[k]);
        		if(pr>0){
        			elements[j][pr].setT(nodes[k].T());
        		}
        		
        	}
        }
	}


};
#endif /* */
